//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension ControlTower {
    // MARK: Enums

    public enum ControlOperationStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case failed = "FAILED"
        case inProgress = "IN_PROGRESS"
        case succeeded = "SUCCEEDED"
        public var description: String { return self.rawValue }
    }

    public enum ControlOperationType: String, CustomStringConvertible, Codable, _SotoSendable {
        case disableControl = "DISABLE_CONTROL"
        case enableControl = "ENABLE_CONTROL"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct ControlOperation: AWSDecodableShape {
        /// The time that the operation finished.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var endTime: Date?
        /// One of ENABLE_CONTROL or DISABLE_CONTROL.
        public let operationType: ControlOperationType?
        /// The time that the operation began.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var startTime: Date?
        /// One of IN_PROGRESS, SUCEEDED, or FAILED.
        public let status: ControlOperationStatus?
        /// If the operation result is FAILED, this string contains a message explaining why the operation failed.
        public let statusMessage: String?

        public init(endTime: Date? = nil, operationType: ControlOperationType? = nil, startTime: Date? = nil, status: ControlOperationStatus? = nil, statusMessage: String? = nil) {
            self.endTime = endTime
            self.operationType = operationType
            self.startTime = startTime
            self.status = status
            self.statusMessage = statusMessage
        }

        private enum CodingKeys: String, CodingKey {
            case endTime
            case operationType
            case startTime
            case status
            case statusMessage
        }
    }

    public struct DisableControlInput: AWSEncodableShape {
        /// The ARN of the control. Only Strongly recommended and Elective controls are permitted, with the exception of the Region deny guardrail.
        public let controlIdentifier: String
        /// The ARN of the organizational unit.
        public let targetIdentifier: String

        public init(controlIdentifier: String, targetIdentifier: String) {
            self.controlIdentifier = controlIdentifier
            self.targetIdentifier = targetIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, max: 2048)
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, min: 20)
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, pattern: "^arn:aws[0-9a-zA-Z_\\-:\\/]+$")
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, max: 2048)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, min: 20)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, pattern: "^arn:aws[0-9a-zA-Z_\\-:\\/]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case controlIdentifier
            case targetIdentifier
        }
    }

    public struct DisableControlOutput: AWSDecodableShape {
        /// The ID of the asynchronous operation, which is used to track status. The operation is available for 90 days.
        public let operationIdentifier: String

        public init(operationIdentifier: String) {
            self.operationIdentifier = operationIdentifier
        }

        private enum CodingKeys: String, CodingKey {
            case operationIdentifier
        }
    }

    public struct EnableControlInput: AWSEncodableShape {
        /// The ARN of the control. Only Strongly recommended and Elective controls are permitted, with the exception of the Region deny guardrail.
        public let controlIdentifier: String
        /// The ARN of the organizational unit.
        public let targetIdentifier: String

        public init(controlIdentifier: String, targetIdentifier: String) {
            self.controlIdentifier = controlIdentifier
            self.targetIdentifier = targetIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, max: 2048)
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, min: 20)
            try self.validate(self.controlIdentifier, name: "controlIdentifier", parent: name, pattern: "^arn:aws[0-9a-zA-Z_\\-:\\/]+$")
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, max: 2048)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, min: 20)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, pattern: "^arn:aws[0-9a-zA-Z_\\-:\\/]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case controlIdentifier
            case targetIdentifier
        }
    }

    public struct EnableControlOutput: AWSDecodableShape {
        /// The ID of the asynchronous operation, which is used to track status. The operation is available for 90 days.
        public let operationIdentifier: String

        public init(operationIdentifier: String) {
            self.operationIdentifier = operationIdentifier
        }

        private enum CodingKeys: String, CodingKey {
            case operationIdentifier
        }
    }

    public struct EnabledControlSummary: AWSDecodableShape {
        /// The ARN of the control. Only Strongly recommended and Elective controls are permitted, with the exception of the Region deny guardrail.
        public let controlIdentifier: String?

        public init(controlIdentifier: String? = nil) {
            self.controlIdentifier = controlIdentifier
        }

        private enum CodingKeys: String, CodingKey {
            case controlIdentifier
        }
    }

    public struct GetControlOperationInput: AWSEncodableShape {
        /// The ID of the asynchronous operation, which is used to track status. The operation is available for 90 days.
        public let operationIdentifier: String

        public init(operationIdentifier: String) {
            self.operationIdentifier = operationIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.operationIdentifier, name: "operationIdentifier", parent: name, max: 36)
            try self.validate(self.operationIdentifier, name: "operationIdentifier", parent: name, min: 36)
            try self.validate(self.operationIdentifier, name: "operationIdentifier", parent: name, pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
        }

        private enum CodingKeys: String, CodingKey {
            case operationIdentifier
        }
    }

    public struct GetControlOperationOutput: AWSDecodableShape {
        public let controlOperation: ControlOperation

        public init(controlOperation: ControlOperation) {
            self.controlOperation = controlOperation
        }

        private enum CodingKeys: String, CodingKey {
            case controlOperation
        }
    }

    public struct ListEnabledControlsInput: AWSEncodableShape {
        /// How many results to return per API call.
        public let maxResults: Int?
        /// The token to continue the list from a previous API call with the same parameters.
        public let nextToken: String?
        /// The ARN of the organizational unit.
        public let targetIdentifier: String

        public init(maxResults: Int? = nil, nextToken: String? = nil, targetIdentifier: String) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.targetIdentifier = targetIdentifier
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, max: 2048)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, min: 20)
            try self.validate(self.targetIdentifier, name: "targetIdentifier", parent: name, pattern: "^arn:aws[0-9a-zA-Z_\\-:\\/]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults
            case nextToken
            case targetIdentifier
        }
    }

    public struct ListEnabledControlsOutput: AWSDecodableShape {
        /// Lists the controls enabled by AWS Control Tower on the specified organizational unit and the accounts it contains.
        public let enabledControls: [EnabledControlSummary]
        /// Retrieves the next page of results. If the string is empty, the current response is the end of the results.
        public let nextToken: String?

        public init(enabledControls: [EnabledControlSummary], nextToken: String? = nil) {
            self.enabledControls = enabledControls
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case enabledControls
            case nextToken
        }
    }
}

// MARK: - Errors

/// Error enum for ControlTower
public struct ControlTowerErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize ControlTower
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// User does not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// Updating or deleting a resource can cause an inconsistent state.
    public static var conflictException: Self { .init(.conflictException) }
    /// Unexpected error during processing of request.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// Request references a resource which does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// Request would cause a service quota to be exceeded. The limit is 10 concurrent operations.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    ///  Request was denied due to request throttling.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// The input fails to satisfy the constraints specified by an AWS service.
    public static var validationException: Self { .init(.validationException) }
}

extension ControlTowerErrorType: Equatable {
    public static func == (lhs: ControlTowerErrorType, rhs: ControlTowerErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension ControlTowerErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
